//
// Created by fairy on 2025/5/18 15:52.
//
module;

#include <type_traits>
#include <cstdint>
#include <bit>
#include <concepts>
#include <project_config.h>
export module bitset;

export namespace utils::bitset
{

    // 值类型版本（创建新变量）
    template <std::unsigned_integral T>
    class BitValue {
        T value;
    public:
        constexpr BitValue() : value(0) {}
        constexpr explicit BitValue(T init) : value(init) {}

        template <size_t Start, size_t End>
        constexpr BitValue& set(auto v) {
            static_assert(Start <= End, "Invalid bit range");
            static_assert(End < sizeof(T)*8, "Bit position out of range");

            constexpr T mask = ((1u << (End - Start + 1)) - 1);
            constexpr T max_value = mask;

            if (v > max_value) { // 改用运行时检查
                // 可抛异常或添加错误处理
                __builtin_unreachable(); // 对于嵌入式场景的优化
            }

            value = (value & ~(mask << Start)) | (static_cast<T>(v) << Start);
            return *this;
        }

        template <size_t Pos>
        constexpr BitValue& set() {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            value |= (1 << Pos);
            return *this;
        }

        template <size_t Start, size_t End>
        constexpr BitValue& clear() {
            static_assert(Start <= End, "Invalid bit range");
            static_assert(End < sizeof(T)*8, "Bit position out of range");
            value &= ~(((static_cast<T>(1) << (End - Start + 1)) - 1) << Start);
            return *this;
        }

        template <size_t Pos>
        constexpr BitValue& clear() {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            value &= ~(static_cast<T>(1) << Pos);
            return *this;
        }

        template <size_t Start, size_t End>
        constexpr BitValue& toggle() {
            static_assert(Start <= End, "Invalid bit range");
            static_assert(End < sizeof(T)*8, "Bit position out of range");
            value ^= (((static_cast<T>(1) << (End - Start + 1)) - 1) << Start);
            return *this;
        }

        template <size_t Pos>
        constexpr BitValue& toggle() {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            value ^= static_cast<T>(1) << Pos;
            return *this;
        }

        template <size_t Pos>
        [[nodiscard]] constexpr bool test() const {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            return (value >> Pos) & 0x1;
        }

        [[nodiscard]] constexpr T get() const { return value; }
        operator T() const { return value; }
    };

// 引用类型版本（修改现有变量）
    template <std::unsigned_integral T>
    class BitRef {
        volatile T& value;
    public:
        explicit constexpr BitRef(volatile T& val) : value(val) {}

        static constexpr BitRef from_ptr(volatile T* ptr) {
            return BitRef(*const_cast<T*>(ptr));
        }

        template <size_t Start, size_t End>
        constexpr BitRef& set(auto v) {
            static_assert(Start <= End, "Invalid bit range");
            static_assert(End < sizeof(T)*8, "Bit position out of range");

            constexpr T mask = ((1 << (End - Start + 1)) - 1);
            static_assert(v <= mask, "Value exceeds bit range capacity");

            value = (value & ~(mask << Start)) | (static_cast<T>(v) << Start);
            return *this;
        }

        template <size_t Pos>
        constexpr BitRef& set() {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            value |= static_cast<T>(1) << Pos;
            return *this;
        }

        template <size_t Start, size_t End>
        constexpr BitRef& clear() {
            static_assert(Start <= End, "Invalid bit range");
            static_assert(End < sizeof(T)*8, "Bit position out of range");
            value &= ~(((static_cast<T>(1) << (End - Start + 1)) - 1) << Start);
            return *this;
        }

        template <size_t Pos>
        constexpr BitRef& clear() {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            value &= ~(static_cast<T>(1) << Pos);
            return *this;
        }

        template <size_t Start, size_t End>
        constexpr BitRef& toggle() {
            static_assert(Start <= End, "Invalid bit range");
            static_assert(End < sizeof(T)*8, "Bit position out of range");
            value ^= (((static_cast<T>(1) << (End - Start + 1)) - 1) << Start);
            return *this;
        }

        template <size_t Pos>
        constexpr BitRef& toggle() {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            value ^= static_cast<T>(1) << Pos;
            return *this;
        }

        template <size_t Pos>
        [[nodiscard]] constexpr bool test() const {
            static_assert(Pos < sizeof(T)*8, "Bit position out of range");
            return (value >> Pos) & 0x1;
        }

        [[nodiscard]] constexpr T get() const { return value; }
        explicit operator T() const { return value; }
    };


    /**
     * 创建位值——工厂函数
     * @tparam Bits
     * @return
     * @note 使用示例
     * @code
            using namespace utils::bitset;

            // 创建新配置（值类型
            auto config = bits<16>()
                    .set<0, 3>(0b1)   // 设置0-3位
                    .set<4>()            // 设置第4位
                    .clear<5>()         // 清除第5位
                    .get();

            // 修改现有变量（引用类型）
            uint16_t existing = 0x1234;
            bits(existing)
                    .toggle<8, 15>()
                    .set<5>();
     *
     */
    template <size_t Bits>
    constexpr auto bits() {
        static_assert(Bits == 8 || Bits == 16 || Bits == 32,
                      "Only 8/16/32 bits supported");
        if constexpr (Bits == 8)  return BitValue<uint8_t>();
        if constexpr (Bits == 16) return BitValue<uint16_t>();
        if constexpr (Bits == 32) return BitValue<uint32_t>();
    }

    template <typename T>
    constexpr BitRef<T> bits(T& val) {
        return BitRef(val);
    }

    template <typename T>
    constexpr BitRef<T> bits(volatile T* ptr) {
        return BitRef<T>::from_ptr(ptr);
    }


}